﻿namespace karlib
{
    using Emgu.CV;
    using Emgu.CV.CvEnum;
    using Emgu.CV.Structure;
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;

    public class klib
    {
        private FileStream conf;
        public double[] dist;
        private List<ProductDistance> distances;
        private double[] hist3;
        private Image<Hsv, byte> img;
        private Image<Bgr, byte> simg;
        private double[,] u;
        private double[,] u2;
        private double[] v;
        private double[] v2;
        private double[] X;
        private double[] X2;

        public klib(string FileName)
        {
            int num;
            int num2;
            this.hist3 = new double[30];
            this.v = new double[10];
            this.X = new double[0x100];
            this.v2 = new double[10];
            this.X2 = new double[180];
            string[] strArray = File.ReadAllLines(FileName);
            this.u = new double[10, 0x100];
            this.u2 = new double[10, 180];
            for (num = 0; num < 10; num++)
            {
                num2 = 0;
                while (num2 < 0x100)
                {
                    this.u[num, num2] = double.Parse(strArray[(0x100 * num) + num2].Split(new char[] { ' ' })[0]);
                    num2++;
                }
            }
            for (num = 0; num < 10; num++)
            {
                for (num2 = 0; num2 < 180; num2++)
                {
                    this.u2[num, num2] = double.Parse(strArray[(0xa01 + (180 * num)) + num2].Split(new char[] { ' ' })[0]);
                }
            }
            this.hist3[0] = 0.0693669276123298;
            this.hist3[1] = 0.640343288823023;
            this.hist3[2] = 0.192700720200092;
            this.hist3[3] = 0.0520074284000599;
            this.hist3[4] = 0.0189917229451947;
            this.hist3[5] = 0.0127039970234863;
            this.hist3[6] = 0.00957547513634219;
            this.hist3[7] = 0.00225595419312182;
            this.hist3[8] = 0.001205168940793;
            this.hist3[9] = 0.000849316725557715;
            this.hist3[10] = 0.102497570409999;
            this.hist3[11] = 0.0901913802562373;
            this.hist3[12] = 0.118068003769081;
            this.hist3[13] = 0.363322145497847;
            this.hist3[14] = 0.214601796845466;
            this.hist3[15] = 0.0565520124979237;
            this.hist3[0x10] = 0.02686811273288;
            this.hist3[0x11] = 0.0150161868441694;
            this.hist3[0x12] = 0.00716603832259873;
            this.hist3[0x13] = 0.00571675282379885;
            this.hist3[20] = 0.0133960360755144;
            this.hist3[0x15] = 0.135945945900859;
            this.hist3[0x16] = 0.172306784339727;
            this.hist3[0x17] = 0.483225241040979;
            this.hist3[0x18] = 0.0333476486252039;
            this.hist3[0x19] = 0.0159799450597377;
            this.hist3[0x1a] = 0.0198949561214832;
            this.hist3[0x1b] = 0.0215934308370415;
            this.hist3[0x1c] = 0.0267449675957642;
            this.hist3[0x1d] = 0.0775650444036892;
        }

        private List<Contour<Point>> CalcContour(Contour<Point> contour, List<Contour<Point>> term)
        {
            term.Add(contour);
            if (contour.VNext != null)
            {
                term = this.CalcContour(contour.VNext, term);
            }
            if (contour.HNext != null)
            {
                term = this.CalcContour(contour.HNext, term);
            }
            return term;
        }

        private void conv(Image<Hsv, byte> image)
        {
            this.simg = image.Convert<Bgr, byte>();
        }

        private string DrawContourdata(Contour<Point>[] contours)
        {
            int num = 0;
            int num2 = 0;
            int num3 = 0;
            int num4 = 0;
            int num5 = 0;
            for (int i = 0; i < contours.Length; i++)
            {
                MemStorage storage = new MemStorage();
                Contour<Point> contour = contours[i];
                if (contour != null)
                {
                    LineSegment2D[] segmentdArray;
                    int num7;
                    double num8;
                    bool flag = true;
                    Contour<Point> contour2 = contour.ApproxPoly(contour.Perimeter * 0.05, storage);
                    Contour<Point> contour3 = contour.ApproxPoly(contour.Perimeter * 0.01, storage);
                    if (contour2.Total == 4)
                    {
                        flag = true;
                        segmentdArray = PointCollection.PolyLine(contour2.ToArray(), true);
                        num7 = 0;
                        while (num7 < segmentdArray.Length)
                        {
                            num8 = Math.Abs(segmentdArray[(num7 + 1) % segmentdArray.Length].GetExteriorAngleDegree(segmentdArray[num7]));
                            if ((num8 < 80.0) || (num8 > 100.0))
                            {
                                flag = false;
                                break;
                            }
                            num7++;
                        }
                        if (flag)
                        {
                            if ((contour2.Area > 10.0) && (contour2.Area <= 50.0))
                            {
                                num5++;
                            }
                            if ((contour2.Area > 50.0) && (contour2.Area <= 500.0))
                            {
                                num4++;
                            }
                            else if (contour2.Area > 500.0)
                            {
                                if (((Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) / Math.Min(contour.BoundingRectangle.Width, contour.BoundingRectangle.Height)) >= 3) && (Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) >= 200))
                                {
                                    num2++;
                                }
                                else
                                {
                                    num++;
                                }
                            }
                        }
                        continue;
                    }
                    if (contour3.Total == 4)
                    {
                        flag = true;
                        segmentdArray = PointCollection.PolyLine(contour3.ToArray(), true);
                        for (num7 = 0; num7 < segmentdArray.Length; num7++)
                        {
                            num8 = Math.Abs(segmentdArray[(num7 + 1) % segmentdArray.Length].GetExteriorAngleDegree(segmentdArray[num7]));
                            if ((num8 < 70.0) || (num8 > 110.0))
                            {
                                flag = false;
                                break;
                            }
                        }
                        if (flag && (contour3.Area > 500.0))
                        {
                            num2++;
                        }
                        continue;
                    }
                    if (((Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) / Math.Min(contour.BoundingRectangle.Width, contour.BoundingRectangle.Height)) >= 5) && (Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) >= 150))
                    {
                        num3 += 30;
                    }
                    else if (((Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) / Math.Min(contour.BoundingRectangle.Width, contour.BoundingRectangle.Height)) >= 5) && (Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) >= 100))
                    {
                        num3 += 10;
                    }
                    else if (((Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) / Math.Min(contour.BoundingRectangle.Width, contour.BoundingRectangle.Height)) >= 5) && (Math.Max(contour3.BoundingRectangle.Width, contour3.BoundingRectangle.Height) >= 30))
                    {
                        num3++;
                    }
                }
            }
            num3 /= 30;
            if ((num > 8) && ((num * 15) > num4))
            {
                return "3";
            }
            if (num4 > 120)
            {
                return "2";
            }
            if (((num2 + num3) >= 4) && ((num2 * 8) > num3))
            {
                return "4";
            }
            if ((num3 < 10) && (num3 >= 4))
            {
                return "4";
            }
            if (num3 >= 10)
            {
                return "5";
            }
            if ((num5 + num4) >= 600)
            {
                num5 += num4;
                return "2";
            }
            return "1";
        }

        private double emd(double[] a, double[] b)
        {
            double num = 0.0;
            double num2 = 0.0;
            for (int i = 0; i < a.Length; i++)
            {
                num = (a[i] + num) - b[i];
                num2 += Math.Abs(num);
            }
            return (num2 / ((double)a.Length));
        }

        private double emd2(double[] a, double[] b)
        {
            double num = 0.0;
            double num2 = 0.0;
            double num3 = 0.0;
            for (int i = 0; i < a.Length; i++)
            {
                for (int j = 0; j <= i; j++)
                {
                    num2 += a[j];
                    num3 += b[j];
                }
                num += Math.Abs((double)(num2 - num3)) / ((double)a.Length);
                num2 = 0.0;
                num3 = 0.0;
            }
            return num;
        }

        private double emd3(double[] a, double[] b)
        {
            double[,] numArray = new double[a.Length, a.Length];
            double[,] numArray2 = new double[a.Length, a.Length];
            double[] source = new double[a.Length];
            double num2 = 0.0;
            for (int i = 0; i < a.Length; i++)
            {
                for (int j = 0; j < a.Length; j++)
                {
                    int num5;
                    numArray[i, j] = 0.0;
                    numArray2[i, j] = 0.0;
                    if (j >= i)
                    {
                        num5 = i;
                        while (num5 < j)
                        {
                            double num1 = numArray[i, j];
                            num1[0] += a[num5];
                            double num7 = numArray2[i, j];
                            num7[0] += b[num5];
                            num5++;
                        }
                    }
                    else if (j < i)
                    {
                        num5 = 0;
                        while (num5 < j)
                        {
                            double num8 = numArray[i, j];
                            num8[0] += a[num5];
                            double num9 = numArray2[i, j];
                            num9[0] += b[num5];
                            num5++;
                        }
                        for (num5 = i; num5 < a.Length; num5++)
                        {
                            double num10 = numArray[i, j];
                            num10[0] += a[num5];
                            double num11 = numArray2[i, j];
                            num11[0] += b[num5];
                        }
                    }
                    num2 += Math.Abs((double)(numArray[i, j] - numArray2[i, j]));
                }
                source[i] = num2;
                num2 = 0.0;
            }
            return (source.Min() / ((double)a.Length));
        }

        private double Euclidian(double[] a, double[] b)
        {
            double d = 0.0;
            for (int i = 0; i < a.Length; i++)
            {
                d += Math.Pow(a[i] - b[i], 2.0);
            }
            return Math.Sqrt(d);
        }

        public double[] ExtractFeatures(Bitmap bitmap)
        {
            this.img = new Image<Hsv, byte>(bitmap);
            this.conv(this.img);
            double[] numArray = new double[0x1f];
            double[] numArray2 = new double[10];
            double[] numArray3 = new double[10];
            double[] numArray4 = new double[10];
            numArray2 = this.Histoh();
            numArray3 = this.Histos();
            numArray4 = this.Histov();
            for (int i = 0; i < 10; i++)
            {
                numArray[i + 1] = numArray2[i];
                numArray[i + 11] = numArray3[i];
                numArray[i + 0x15] = numArray4[i];
            }
            numArray[0] = double.Parse(this.Shape());
            return numArray;
        }

        public double[] ExtractFeatures(string FileName)
        {
            this.img = new Image<Hsv, byte>(FileName);
            this.conv(this.img);
            double[] numArray = new double[0x1f];
            double[] numArray2 = new double[10];
            double[] numArray3 = new double[10];
            double[] numArray4 = new double[10];
            numArray2 = this.Histoh();
            numArray3 = this.Histos();
            numArray4 = this.Histov();
            for (int i = 0; i < 10; i++)
            {
                numArray[i + 1] = numArray2[i];
                numArray[i + 11] = numArray3[i];
                numArray[i + 0x15] = numArray4[i];
            }
            numArray[0] = double.Parse(this.Shape());
            return numArray;
        }

        private double[] ExtractFeatures2(string FileName)
        {
            this.img = new Image<Hsv, byte>(FileName);
            this.conv(this.img);
            double[] numArray = new double[0x1f];
            double[] numArray2 = new double[10];
            double[] numArray3 = new double[10];
            double[] numArray4 = new double[10];
            numArray2 = this.Histoh();
            numArray3 = this.Histos();
            numArray4 = this.Histov();
            for (int i = 0; i < 10; i++)
            {
                numArray[i + 1] = numArray2[i];
                numArray[i + 11] = numArray3[i];
                numArray[i + 0x15] = numArray4[i];
            }
            numArray[0] = double.Parse(this.Shapeold());
            return numArray;
        }

        private double[] ExtractFeaturescol(string FileName)
        {
            this.img = new Image<Hsv, byte>(FileName);
            this.conv(this.img);
            double[] numArray = new double[30];
            double[] numArray2 = new double[10];
            double[] numArray3 = new double[10];
            double[] numArray4 = new double[10];
            numArray2 = this.Histoh();
            numArray3 = this.Histos();
            numArray4 = this.Histov();
            for (int i = 0; i < 10; i++)
            {
                numArray[i] = numArray2[i];
                numArray[i + 10] = numArray3[i];
                numArray[i + 20] = numArray4[i];
            }
            return numArray;
        }

        public bool find(string FileName)
        {
            int num;
            int num2;
            this.img = new Image<Hsv, byte>(FileName);
            this.conv(this.img);
            double[] b = new double[30];
            double[] numArray2 = new double[10];
            double[] numArray3 = new double[10];
            double[] numArray4 = new double[10];
            Image<Hsv, byte> imgc = new Image<Hsv, byte>(0x4b, 60);
            for (num = 0xb7; num < 0xf3; num++)
            {
                num2 = 0x1a9;
                while (num2 < 500)
                {
                    imgc[num - 0xb7, num2 - 0x1a9] = this.img[num, num2];
                    num2++;
                }
            }
            numArray2 = this.Histoh2(imgc);
            numArray3 = this.Histos2(imgc);
            numArray4 = this.Histov2(imgc);
            for (int i = 0; i < 10; i++)
            {
                b[i] = numArray2[i];
                b[i + 10] = numArray3[i];
                b[i + 20] = numArray4[i];
            }
            int num4 = 0;
            int num5 = 0;
            double num6 = 0.0;
            double num7 = 0.0;
            Image<Gray, byte> image2 = this.img.Convert<Gray, byte>();
            for (num = 0; num < image2.Height; num++)
            {
                for (num2 = 0; num2 < image2.Width; num2++)
                {
                    Gray gray;
                    if ((((num < 110) || (num > 390)) || (num2 < 110)) || (num2 > 390))
                    {
                        gray = image2[num, num2];
                        if (gray.Intensity < 250.0)
                        {
                            num4 = 1;
                        }
                    }
                    else
                    {
                        gray = image2[num, num2];
                        if (gray.Intensity > 250.0)
                        {
                            num6++;
                        }
                        num7++;
                    }
                }
            }
            num7 = num6 / num7;
            if (num7 > 0.9)
            {
                num5 = 1;
            }
            return ((this.Euclidian(this.hist3, b) < 0.4) || ((num4 == 0) && (num5 == 0)));
        }

        private List<int> GetSimilarsTopN2(double[] FeatureVector, Dictionary<int, double[]> DatabaseFeatures, int Threshold, List<double> Weights = null)
        {
            int[] numArray = DatabaseFeatures.Keys.ToArray<int>();
            double[][] numArray2 = DatabaseFeatures.Values.ToArray<double[]>();
            double[] a = new double[10];
            double[] numArray4 = new double[10];
            double[] numArray5 = new double[10];
            double[] b = new double[10];
            double[] numArray7 = new double[10];
            double[] numArray8 = new double[10];
            int[] numArray9 = new int[numArray2.Length];
            this.dist = new double[numArray2.Length];
            List<int> list = new List<int>();
            double[] numArray10 = new double[FeatureVector.Length];
            double num3 = 1.0;
            double num4 = 1.0;
            double num5 = 1.0;
            if (Weights != null)
            {
                num3 = Weights[0];
                num4 = Weights[1];
                num5 = Weights[2];
            }
            int index = 0;
            while (index < 10)
            {
                a[index] = FeatureVector[index + 1];
                numArray4[index] = FeatureVector[index + 11];
                numArray5[index] = FeatureVector[index + 0x15];
                index++;
            }
            double num = FeatureVector[0];
            for (int i = 0; i < numArray2.Length; i++)
            {
                double num2 = numArray2[i][0];
                if (num == num2)
                {
                    for (index = 0; index < 10; index++)
                    {
                        b[index] = numArray2[i][index + 1];
                        numArray7[index] = numArray2[i][index + 11];
                        numArray8[index] = numArray2[i][index + 0x15];
                    }
                    this.dist[i] = (((num3 * this.Euclidian(a, b)) + (num4 * this.Euclidian(numArray4, numArray7))) + (num5 * this.Euclidian(numArray5, numArray8))) / ((num3 + num4) + num5);
                }
                else
                {
                    this.dist[i] = 10000000000000;
                }
                numArray9[i] = numArray[i];
            }
            this.distances = new List<ProductDistance>();
            for (int j = 0; j < this.dist.Length; j++)
            {
                this.distances.Add(new ProductDistance(numArray9[j], this.dist[j]));
            }
            return (from p in
                        (from x in this.distances
                         orderby x.Distance
                         select x).Take<ProductDistance>(Threshold)
                    select p.ProductId).ToList<int>();
        }

        private List<int> GetSimilarsTopNemd(double[] FeatureVector, Dictionary<int, double[]> DatabaseFeatures, int Threshold, List<double> Weights = null)
        {
            int[] numArray = DatabaseFeatures.Keys.ToArray<int>();
            double[][] numArray2 = DatabaseFeatures.Values.ToArray<double[]>();
            double[] a = new double[10];
            double[] numArray4 = new double[10];
            double[] numArray5 = new double[10];
            double[] b = new double[10];
            double[] numArray7 = new double[10];
            double[] numArray8 = new double[10];
            int[] items = new int[numArray2.Length];
            this.dist = new double[numArray2.Length];
            List<int> list = new List<int>();
            double[] numArray10 = new double[FeatureVector.Length];
            double num3 = 1.0;
            double num4 = 1.0;
            double num5 = 1.0;
            if (Weights != null)
            {
                num3 = Weights[0];
                num4 = Weights[1];
                num5 = Weights[2];
            }
            int index = 0;
            while (index < 10)
            {
                a[index] = FeatureVector[index + 1];
                numArray4[index] = FeatureVector[index + 11];
                numArray5[index] = FeatureVector[index + 0x15];
                index++;
            }
            double num = FeatureVector[0];
            for (int i = 0; i < numArray2.Length; i++)
            {
                double num2 = numArray2[i][0];
                if (num == num2)
                {
                    for (index = 0; index < 10; index++)
                    {
                        b[index] = numArray2[i][index + 1];
                        numArray7[index] = numArray2[i][index + 11];
                        numArray8[index] = numArray2[i][index + 0x15];
                    }
                    this.dist[i] = (((num3 * this.emd(a, b)) + (num4 * this.emd(numArray4, numArray7))) + (num5 * this.emd(numArray5, numArray8))) / ((num3 + num4) + num5);
                }
                else
                {
                    this.dist[i] = 10000000000000;
                }
                items[i] = numArray[i];
            }
            Array.Sort<double, int>(this.dist, items);
            for (int j = 0; j < Threshold; j++)
            {
                list.Add(items[j]);
            }
            return list;
        }

        private List<int> GetSimilarsTopNemd2(double[] FeatureVector, Dictionary<int, double[]> DatabaseFeatures, int Threshold, List<double> Weights = null)
        {
            int[] numArray = DatabaseFeatures.Keys.ToArray<int>();
            double[][] numArray2 = DatabaseFeatures.Values.ToArray<double[]>();
            double[] a = new double[10];
            double[] numArray4 = new double[10];
            double[] numArray5 = new double[10];
            double[] b = new double[10];
            double[] numArray7 = new double[10];
            double[] numArray8 = new double[10];
            int[] items = new int[numArray2.Length];
            this.dist = new double[numArray2.Length];
            List<int> list = new List<int>();
            double[] numArray10 = new double[FeatureVector.Length];
            double num3 = 1.0;
            double num4 = 1.0;
            double num5 = 1.0;
            if (Weights != null)
            {
                num3 = Weights[0];
                num4 = Weights[1];
                num5 = Weights[2];
            }
            int index = 0;
            while (index < 10)
            {
                a[index] = FeatureVector[index + 1];
                numArray4[index] = FeatureVector[index + 11];
                numArray5[index] = FeatureVector[index + 0x15];
                index++;
            }
            double num = FeatureVector[0];
            for (int i = 0; i < numArray2.Length; i++)
            {
                double num2 = numArray2[i][0];
                if (num == num2)
                {
                    for (index = 0; index < 10; index++)
                    {
                        b[index] = numArray2[i][index + 1];
                        numArray7[index] = numArray2[i][index + 11];
                        numArray8[index] = numArray2[i][index + 0x15];
                    }
                    this.dist[i] = (((num3 * this.emd3(a, b)) + (num4 * this.emd3(numArray4, numArray7))) + (num5 * this.emd3(numArray5, numArray8))) / ((num3 + num4) + num5);
                }
                else
                {
                    this.dist[i] = 10000000000000;
                }
                items[i] = numArray[i];
            }
            Array.Sort<double, int>(this.dist, items);
            for (int j = 0; j < Threshold; j++)
            {
                list.Add(items[j]);
            }
            return list;
        }

        private List<int> GetSimilarsTopNemdson(double[] FeatureVector, Dictionary<int, double[]> DatabaseFeatures, int Threshold, List<double> Weights = null)
        {
            int[] numArray = DatabaseFeatures.Keys.ToArray<int>();
            double[][] numArray2 = DatabaseFeatures.Values.ToArray<double[]>();
            double[] a = new double[10];
            double[] numArray4 = new double[10];
            double[] numArray5 = new double[10];
            double[] b = new double[10];
            double[] numArray7 = new double[10];
            double[] numArray8 = new double[10];
            int[] items = new int[numArray2.Length];
            this.dist = new double[numArray2.Length];
            List<int> list = new List<int>();
            double[] numArray10 = new double[FeatureVector.Length];
            double num3 = 1.0;
            double num4 = 1.0;
            double num5 = 1.0;
            if (Weights != null)
            {
                num3 = Weights[0];
                num4 = Weights[1];
                num5 = Weights[2];
            }
            int index = 0;
            while (index < 10)
            {
                a[index] = FeatureVector[index + 1];
                numArray4[index] = FeatureVector[index + 11];
                numArray5[index] = FeatureVector[index + 0x15];
                index++;
            }
            double num = FeatureVector[0];
            for (int i = 0; i < numArray2.Length; i++)
            {
                double num2 = numArray2[i][0];
                if (num == num2)
                {
                    for (index = 0; index < 10; index++)
                    {
                        b[index] = numArray2[i][index + 1];
                        numArray7[index] = numArray2[i][index + 11];
                        numArray8[index] = numArray2[i][index + 0x15];
                    }
                    this.dist[i] = (((num3 * this.emd3(a, b)) + (num4 * this.emd2(numArray4, numArray7))) + (num5 * this.emd2(numArray5, numArray8))) / ((num3 + num4) + num5);
                }
                else
                {
                    this.dist[i] = 10000000000000;
                }
                items[i] = numArray[i];
            }
            Array.Sort<double, int>(this.dist, items);
            for (int j = 0; j < Threshold; j++)
            {
                list.Add(items[j]);
            }
            return list;
        }

        public double[] Histoh()
        {
            int num;
            double[] numArray = new double[180];
            double[] numArray2 = new double[10];
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] = 0.0;
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                numArray2[num] = 0.0;
            }
            for (int i = 0; i < this.img.Height; i++)
            {
                for (int j = 0; j < this.img.Width; j++)
                {
                    Hsv hsv = this.img[i, j];
                    numArray[Convert.ToInt32(hsv.Hue)]++;
                }
            }
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] /= (double)(this.img.Height * this.img.Width);
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                for (int k = 0; k < numArray.Length; k++)
                {
                    numArray2[num] += numArray[k] * this.u2[num, k];
                }
            }
            return numArray2;
        }

        private double[] Histoh2(Image<Hsv, byte> imgc)
        {
            int num;
            double[] numArray = new double[180];
            double[] numArray2 = new double[10];
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] = 0.0;
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                numArray2[num] = 0.0;
            }
            for (int i = 0; i < imgc.Height; i++)
            {
                for (int j = 0; j < imgc.Width; j++)
                {
                    Hsv hsv = imgc[i, j];
                    numArray[Convert.ToInt32(hsv.Hue)]++;
                }
            }
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] /= (double)(imgc.Height * imgc.Width);
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                for (int k = 0; k < numArray.Length; k++)
                {
                    numArray2[num] += numArray[k] * this.u2[num, k];
                }
            }
            return numArray2;
        }

        public double[] Histos()
        {
            int num;
            double[] numArray = new double[0x100];
            double[] numArray2 = new double[10];
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] = 0.0;
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                numArray2[num] = 0.0;
            }
            for (int i = 0; i < this.img.Height; i++)
            {
                for (int j = 0; j < this.img.Width; j++)
                {
                    Hsv hsv = this.img[i, j];
                    numArray[Convert.ToInt32(hsv.Satuation)]++;
                }
            }
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] /= (double)(this.img.Height * this.img.Width);
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                for (int k = 0; k < numArray.Length; k++)
                {
                    numArray2[num] += numArray[k] * this.u[num, k];
                }
            }
            return numArray2;
        }

        private double[] Histos2(Image<Hsv, byte> imgc)
        {
            int num;
            double[] numArray = new double[0x100];
            double[] numArray2 = new double[10];
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] = 0.0;
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                numArray2[num] = 0.0;
            }
            for (int i = 0; i < imgc.Height; i++)
            {
                for (int j = 0; j < imgc.Width; j++)
                {
                    Hsv hsv = imgc[i, j];
                    numArray[Convert.ToInt32(hsv.Satuation)]++;
                }
            }
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] /= (double)(imgc.Height * imgc.Width);
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                for (int k = 0; k < numArray.Length; k++)
                {
                    numArray2[num] += numArray[k] * this.u[num, k];
                }
            }
            return numArray2;
        }

        public double[] Histov()
        {
            int num;
            double[] numArray = new double[0x100];
            double[] numArray2 = new double[10];
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] = 0.0;
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                numArray2[num] = 0.0;
            }
            for (int i = 0; i < this.img.Height; i++)
            {
                for (int j = 0; j < this.img.Width; j++)
                {
                    Hsv hsv = this.img[i, j];
                    numArray[Convert.ToInt32(hsv.Value)]++;
                }
            }
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] /= (double)(this.img.Height * this.img.Width);
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                for (int k = 0; k < numArray.Length; k++)
                {
                    numArray2[num] += numArray[k] * this.u[num, k];
                }
            }
            return numArray2;
        }

        private double[] Histov2(Image<Hsv, byte> imgc)
        {
            int num;
            double[] numArray = new double[0x100];
            double[] numArray2 = new double[10];
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] = 0.0;
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                numArray2[num] = 0.0;
            }
            for (int i = 0; i < imgc.Height; i++)
            {
                for (int j = 0; j < imgc.Width; j++)
                {
                    Hsv hsv = imgc[i, j];
                    numArray[Convert.ToInt32(hsv.Value)]++;
                }
            }
            for (num = 0; num < numArray.Length; num++)
            {
                numArray[num] /= (double)(imgc.Height * imgc.Width);
            }
            for (num = 0; num < numArray2.Length; num++)
            {
                for (int k = 0; k < numArray.Length; k++)
                {
                    numArray2[num] += numArray[k] * this.u[num, k];
                }
            }
            return numArray2;
        }

        private void LoadConfig(FileStream ConfigFile)
        {
            this.conf = ConfigFile;
        }

        private double[,] Matr(double m, double er, double[] X, ref double[] v)
        {
            int num3;
            int num4;
            double num5;
            double num6;
            double num7;
            int num8;
            double num12;
            int length = X.Length;
            int num = v.Length;
            double[] numArray = new double[num];
            double[] numArray2 = new double[num];
            double[,] numArray3 = new double[num, length];
            for (num3 = 0; num3 < num; num3++)
            {
                num4 = 0;
                while (num4 < length)
                {
                    num5 = 0.0;
                    num6 = 0.0;
                    num7 = 0.0;
                    if ((X[num4] - v[num3]) == 0.0)
                    {
                        numArray3[num3, num4] = 1.0;
                    }
                    else
                    {
                        num7 = Math.Pow(X[num4] - v[num3], 2.0);
                        num7 = Math.Pow(1.0 / num7, 1.0 / (m - 1.0));
                        num8 = 0;
                        while (num8 < num)
                        {
                            num6 = Math.Pow(X[num4] - v[num8], 2.0);
                            num6 = 1.0 / num6;
                            num5 += Math.Pow(num6, 1.0 / (m - 1.0));
                            num8++;
                        }
                        numArray3[num3, num4] = num7 / num5;
                    }
                    num4++;
                }
            }
            num3 = 0;
            while (num3 < num)
            {
                numArray[num3] = 0.0;
                num4 = 0;
                while (num4 < length)
                {
                    numArray[num3] += numArray3[num3, num4];
                    num4++;
                }
                numArray[num3] /= (double)length;
                num3++;
            }
            for (double i = 100.0; i > er; i = Math.Sqrt(num12))
            {
                num3 = 0;
                while (num3 < num)
                {
                    numArray2[num3] = numArray[num3];
                    num3++;
                }
                num3 = 0;
                while (num3 < num)
                {
                    double num10 = 0.0;
                    double num11 = 0.0;
                    num4 = 0;
                    while (num4 < length)
                    {
                        num10 += Math.Pow(numArray3[num3, num4], m) * X[num4];
                        num11 += Math.Pow(numArray3[num3, num4], m);
                        num4++;
                    }
                    v[num3] = num10 / num11;
                    num3++;
                }
                num3 = 0;
                while (num3 < num)
                {
                    num4 = 0;
                    while (num4 < length)
                    {
                        num5 = 0.0;
                        num6 = 0.0;
                        num7 = 0.0;
                        if ((X[num4] - v[num3]) == 0.0)
                        {
                            numArray3[num3, num4] = 1.0;
                        }
                        else
                        {
                            num7 = Math.Pow(X[num4] - v[num3], 2.0);
                            num7 = Math.Pow(1.0 / num7, 1.0 / (m - 1.0));
                            for (num8 = 0; num8 < num; num8++)
                            {
                                num6 = Math.Pow(X[num4] - v[num8], 2.0);
                                num6 = 1.0 / num6;
                                num5 += Math.Pow(num6, 1.0 / (m - 1.0));
                            }
                            numArray3[num3, num4] = num7 / num5;
                        }
                        num4++;
                    }
                    num3++;
                }
                num3 = 0;
                while (num3 < num)
                {
                    numArray[num3] = 0.0;
                    for (num4 = 0; num4 < length; num4++)
                    {
                        numArray[num3] += numArray3[num3, num4];
                    }
                    numArray[num3] /= (double)length;
                    num3++;
                }
                num12 = 0.0;
                for (num3 = 0; num3 < num; num3++)
                {
                    num12 += Math.Pow(numArray[num3] - numArray2[num3], 2.0);
                }
            }
            return numArray3;
        }

        public string Shape()
        {
            string str = null;
            MemStorage stor = new MemStorage();
            Gray thresh = new Gray(100.0);
            Gray threshLinking = new Gray(50.0);
            List<Contour<Point>> term = new List<Contour<Point>>();
            Image<Gray, byte> image = this.simg[0].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image2 = this.simg[1].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image3 = this.simg[2].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Bgr, byte> image4 = new Image<Bgr, byte>(this.simg.Size);
            image4[0] = image.Canny(thresh, threshLinking);
            image4[1] = image2.Canny(thresh, threshLinking);
            image4[2] = image3.Canny(thresh, threshLinking);
            for (int i = 0; i < image4.Height; i++)
            {
                for (int j = 0; j < image4.Width; j++)
                {
                    Bgr bgr = image4[i, j];
                    if (((((bgr.Blue != 0.0) || (bgr.Green != 0.0)) || ((bgr.Red != 0.0) || (i <= 1))) || ((j <= 1) || (i >= (image4.Height - 2)))) || (j >= (image4.Width - 2)))
                    {
                        bgr.Blue = 255.0;
                        bgr.Green = 255.0;
                        bgr.Red = 255.0;
                        image4[i, j] = bgr;
                    }
                }
            }
            Contour<Point> contour = image4.Convert<Gray, byte>().Dilate(1).Erode(1).FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, RETR_TYPE.CV_RETR_TREE, stor);
            if (contour != null)
            {
                term = this.CalcContour(contour, term);
            }
            Contour<Point>[] contours = term.ToArray();
            str = this.DrawContourdata(contours);
            if ((str == "1") && (double.Parse(this.Vertical(this.simg, 10)) <= 30.0))
            {
                return "6";
            }
            if ((str == "1") && (double.Parse(this.Vertical3(this.simg)) >= 4500.0))
            {
                str = "6";
            }
            return str;
        }

        private string Shapenew(string FileName)
        {
            Image<Bgr, byte> simg = new Image<Bgr, byte>(FileName);
            string str = null;
            MemStorage stor = new MemStorage();
            Gray thresh = new Gray(100.0);
            Gray threshLinking = new Gray(50.0);
            List<Contour<Point>> term = new List<Contour<Point>>();
            Image<Gray, byte> image2 = simg[0].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image3 = simg[1].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image4 = simg[2].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Bgr, byte> image5 = new Image<Bgr, byte>(simg.Size);
            image5[0] = image2.Canny(thresh, threshLinking);
            image5[1] = image3.Canny(thresh, threshLinking);
            image5[2] = image4.Canny(thresh, threshLinking);
            for (int i = 0; i < image5.Height; i++)
            {
                for (int j = 0; j < image5.Width; j++)
                {
                    Bgr bgr = image5[i, j];
                    if (((((bgr.Blue != 0.0) || (bgr.Green != 0.0)) || ((bgr.Red != 0.0) || (i <= 1))) || ((j <= 1) || (i >= (image5.Height - 2)))) || (j >= (image5.Width - 2)))
                    {
                        bgr.Blue = 255.0;
                        bgr.Green = 255.0;
                        bgr.Red = 255.0;
                        image5[i, j] = bgr;
                    }
                }
            }
            Contour<Point> contour = image5.Convert<Gray, byte>().Dilate(1).Erode(1).FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, RETR_TYPE.CV_RETR_TREE, stor);
            if (contour != null)
            {
                term = this.CalcContour(contour, term);
            }
            Contour<Point>[] contours = term.ToArray();
            str = this.DrawContourdata(contours);
            if ((str == "1") && (double.Parse(this.Vertical(simg, 10)) <= 30.0))
            {
                return "6";
            }
            if ((str == "1") && (double.Parse(this.Vertical3(simg)) >= 4500.0))
            {
                str = "6";
            }
            return str;
        }

        private string Shapenew2(string FileName)
        {
            Image<Bgr, byte> simg = new Image<Bgr, byte>(FileName);
            string str = "1";
            if (double.Parse(this.Vertical(simg, 10)) <= 30.0)
            {
                return "6";
            }
            if (double.Parse(this.Vertical3(simg)) >= 4500.0)
            {
                str = "6";
            }
            return str;
        }

        private string Shapeold()
        {
            string str = null;
            MemStorage stor = new MemStorage();
            Gray thresh = new Gray(100.0);
            Gray threshLinking = new Gray(50.0);
            List<Contour<Point>> term = new List<Contour<Point>>();
            Image<Gray, byte> image = this.simg[0].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image2 = this.simg[1].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image3 = this.simg[2].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Bgr, byte> image4 = new Image<Bgr, byte>(this.simg.Size);
            image4[0] = image.Canny(thresh, threshLinking);
            image4[1] = image2.Canny(thresh, threshLinking);
            image4[2] = image3.Canny(thresh, threshLinking);
            for (int i = 0; i < image4.Height; i++)
            {
                for (int j = 0; j < image4.Width; j++)
                {
                    Bgr bgr = image4[i, j];
                    if (((((bgr.Blue != 0.0) || (bgr.Green != 0.0)) || ((bgr.Red != 0.0) || (i <= 1))) || ((j <= 1) || (i >= (image4.Height - 2)))) || (j >= (image4.Width - 2)))
                    {
                        bgr.Blue = 255.0;
                        bgr.Green = 255.0;
                        bgr.Red = 255.0;
                        image4[i, j] = bgr;
                    }
                }
            }
            Contour<Point> contour = image4.Convert<Gray, byte>().Dilate(1).Erode(1).FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, RETR_TYPE.CV_RETR_TREE, stor);
            if (contour != null)
            {
                term = this.CalcContour(contour, term);
            }
            Contour<Point>[] contours = term.ToArray();
            str = this.DrawContourdata(contours);
            if ((double.Parse(this.Vertical(this.simg, 10)) <= 52.0) && (str != "1"))
            {
                return "1";
            }
            if ((double.Parse(this.Vertical2(this.simg, 10)) <= 75.0) && (this.DrawContourdata(contours) != "1"))
            {
                str = "1";
            }
            return str;
        }

        private string Vertical(Image<Bgr, byte> simg, int hor)
        {
            float[, ,] data;
            int num4;
            int num5;
            int num6;
            double num3 = 0.0;
            int height = simg.Height;
            Image<Gray, byte> image = simg[0].Convert<Gray, byte>().PyrDown().PyrUp();
            image.ROI = new Rectangle(0, image.Height / 2, image.Width, hor);
            Image<Gray, byte> image2 = new Image<Gray, byte>(image.Width, hor);
            image2 = image.Copy();
            Image<Gray, byte> template = new Image<Gray, byte>(image.Width, hor);
            image = simg[0].Convert<Gray, byte>().PyrDown().PyrUp();
            for (num4 = 8; num4 < (height - 8); num4 += hor)
            {
                num5 = 0;
                while (num5 < hor)
                {
                    num6 = 0;
                    while (num6 < image.Width)
                    {
                        template[num5, num6] = image[num5 + num4, num6];
                        num6++;
                    }
                    num5++;
                }
                data = image2.MatchTemplate(template, TM_TYPE.CV_TM_CCOEFF_NORMED).Data;
                num3 += Math.Abs(data[0, 0, 0]);
            }
            Image<Gray, byte> image5 = simg[1].Convert<Gray, byte>().PyrDown().PyrUp();
            image5.ROI = new Rectangle(0, image.Height / 2, image5.Width, hor);
            Image<Gray, byte> image6 = new Image<Gray, byte>(image5.Width, hor);
            image6 = image5.Copy();
            Image<Gray, byte> image7 = new Image<Gray, byte>(image5.Width, hor);
            image5 = simg[1].Convert<Gray, byte>().PyrDown().PyrUp();
            for (num4 = 8; num4 < (height - 8); num4 += hor)
            {
                num5 = 0;
                while (num5 < hor)
                {
                    num6 = 0;
                    while (num6 < image5.Width)
                    {
                        image7[num5, num6] = image5[num5 + num4, num6];
                        num6++;
                    }
                    num5++;
                }
                data = image6.MatchTemplate(image7, TM_TYPE.CV_TM_CCOEFF_NORMED).Data;
                num3 += Math.Abs(data[0, 0, 0]);
            }
            Image<Gray, byte> image9 = simg[2].Convert<Gray, byte>().PyrDown().PyrUp();
            image9.ROI = new Rectangle(0, image.Height / 2, image9.Width, hor);
            Image<Gray, byte> image10 = new Image<Gray, byte>(image9.Width, hor);
            image10 = image9.Copy();
            Image<Gray, byte> image11 = new Image<Gray, byte>(image9.Width, hor);
            image9 = simg[2].Convert<Gray, byte>().PyrDown().PyrUp();
            for (num4 = 8; num4 < (height - 8); num4 += hor)
            {
                for (num5 = 0; num5 < hor; num5++)
                {
                    for (num6 = 0; num6 < image9.Width; num6++)
                    {
                        image11[num5, num6] = image9[num5 + num4, num6];
                    }
                }
                data = image10.MatchTemplate(image11, TM_TYPE.CV_TM_CCOEFF_NORMED).Data;
                num3 += Math.Abs(data[0, 0, 0]);
            }
            int num = (int)num3;
            image.Dispose();
            image2.Dispose();
            template.Dispose();
            image5.Dispose();
            image6.Dispose();
            image7.Dispose();
            image9.Dispose();
            image10.Dispose();
            image11.Dispose();
            return num.ToString();
        }

        private string Vertical2(Image<Bgr, byte> simg, int hor)
        {
            int num4;
            int num5;
            Gray gray;
            Image<Gray, byte> image = simg[0].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image2 = simg[1].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image3 = simg[2].Convert<Gray, byte>().PyrDown().PyrUp();
            double num2 = 0.0;
            double num3 = 0.0;
            for (num4 = 0; num4 < image.Width; num4++)
            {
                num5 = image.Height / 2;
                while (num5 < ((image.Height / 2) + hor))
                {
                    gray = image[num5, num4];
                    num2 += gray.Intensity;
                    num5++;
                }
            }
            num2 /= (double)(image.Width * hor);
            for (num4 = 0; num4 < image.Width; num4++)
            {
                num5 = image.Height / 2;
                while (num5 < ((image.Height / 2) + hor))
                {
                    gray = image[num5, num4];
                    num3 += Math.Abs((double)(num2 - gray.Intensity));
                    num5++;
                }
            }
            num2 = 0.0;
            for (num4 = 0; num4 < image2.Width; num4++)
            {
                num5 = image.Height / 2;
                while (num5 < ((image.Height / 2) + hor))
                {
                    gray = image2[num5, num4];
                    num2 += gray.Intensity;
                    num5++;
                }
            }
            num2 /= (double)(image.Width * hor);
            for (num4 = 0; num4 < image2.Width; num4++)
            {
                num5 = image.Height / 2;
                while (num5 < ((image.Height / 2) + hor))
                {
                    gray = image2[num5, num4];
                    num3 += Math.Abs((double)(num2 - gray.Intensity));
                    num5++;
                }
            }
            num2 = 0.0;
            for (num4 = 0; num4 < image3.Width; num4++)
            {
                num5 = image.Height / 2;
                while (num5 < ((image.Height / 2) + hor))
                {
                    gray = image3[num5, num4];
                    num2 += gray.Intensity;
                    num5++;
                }
            }
            num2 /= (double)(image.Width * hor);
            for (num4 = 0; num4 < image3.Width; num4++)
            {
                for (num5 = image.Height / 2; num5 < ((image.Height / 2) + hor); num5++)
                {
                    gray = image3[num5, num4];
                    num3 += Math.Abs((double)(num2 - gray.Intensity));
                }
            }
            num3 /= 2500.0;
            image.Dispose();
            image2.Dispose();
            image3.Dispose();
            int num = (int)num3;
            return num.ToString();
        }

        private string Vertical3(Image<Bgr, byte> simg)
        {
            int num4;
            int num5;
            Gray gray;
            Image<Gray, byte> image = simg[0].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image2 = simg[1].Convert<Gray, byte>().PyrDown().PyrUp();
            Image<Gray, byte> image3 = simg[2].Convert<Gray, byte>().PyrDown().PyrUp();
            double num2 = 0.0;
            double num3 = 0.0;
            for (num4 = 0; num4 < image.Width; num4++)
            {
                num5 = 0;
                while (num5 < image.Height)
                {
                    gray = image[num5, num4];
                    num2 += gray.Intensity;
                    num5++;
                }
            }
            num2 /= (double)(image.Width * image.Height);
            for (num4 = 0; num4 < image.Width; num4++)
            {
                num5 = 0;
                while (num5 < image.Height)
                {
                    gray = image[num5, num4];
                    num3 += Math.Abs((double)(num2 - gray.Intensity));
                    num5++;
                }
            }
            num2 = 0.0;
            for (num4 = 0; num4 < image2.Width; num4++)
            {
                num5 = 0;
                while (num5 < image.Height)
                {
                    gray = image2[num5, num4];
                    num2 += gray.Intensity;
                    num5++;
                }
            }
            num2 /= (double)(image.Width * image.Height);
            for (num4 = 0; num4 < image2.Width; num4++)
            {
                num5 = 0;
                while (num5 < image.Height)
                {
                    gray = image2[num5, num4];
                    num3 += Math.Abs((double)(num2 - gray.Intensity));
                    num5++;
                }
            }
            num2 = 0.0;
            for (num4 = 0; num4 < image3.Width; num4++)
            {
                num5 = 0;
                while (num5 < image.Height)
                {
                    gray = image3[num5, num4];
                    num2 += gray.Intensity;
                    num5++;
                }
            }
            num2 /= (double)(image.Width * image.Height);
            for (num4 = 0; num4 < image3.Width; num4++)
            {
                for (num5 = 0; num5 < image.Height; num5++)
                {
                    gray = image3[num5, num4];
                    num3 += Math.Abs((double)(num2 - gray.Intensity));
                }
            }
            num3 /= 2500.0;
            image.Dispose();
            image2.Dispose();
            image3.Dispose();
            int num = (int)num3;
            return num.ToString();
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct ProductDistance
        {
            public int ProductId;
            public double Distance;
            public ProductDistance(int x, double y)
            {
                this.ProductId = x;
                this.Distance = y;
            }
        }
    }
}

